package cn.pku.edu.cs.ldn.view;

import cn.pku.edu.cs.ldn.R;
import cn.pku.edu.cs.ldn.util.ImageUtil;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;

public class ExtendedImageView extends WebImageView {
	private static final String TAG = "FixedRatioImage";
	private static final boolean DEBUG = true;

	private int imageWidth;
	private int imageHeight;

	public final static int FIT_WIDTH = 0;
	public final static int FIT_HEIGHT = 1;
	private int fitType = -1;

	private int radiusX = 0;
	private int radiusY = 0;
	private boolean round = false;

	public ExtendedImageView(Context context) {
		super(context);
		init(context, null);
	}

	public ExtendedImageView(Context context, AttributeSet attrs) {
		super(context, attrs);
		init(context, attrs);
	}

	public ExtendedImageView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		init(context, attrs);
	}

	private void init(Context context, AttributeSet attrs) {
		if (DEBUG)
			Log.v(TAG, "init");
		if (attrs != null) {
			TypedArray a = context.obtainStyledAttributes(attrs,
					R.styleable.extend);
			radiusX = a.getInt(R.styleable.extend_radiusX, 0);
			radiusY = a.getInt(R.styleable.extend_radiusY, 0);
			fitType = a.getInt(R.styleable.extend_fitType, -1);
			round = a.getBoolean(R.styleable.extend_round, false);
			if (DEBUG)
				Log.v(TAG, "init: radiusX " + radiusX + " radiusY " + radiusY
						+ " fitType " + fitType + " round " + round);
			if (radiusX > 0 || radiusY > 0 || round) {
				Drawable d = getDrawable();
				if (d != null) {
					setImageDrawable(d);
				}
			}
			a.recycle();
		}
		delayImageLoading = false;
	}

	@Override
	public void setImageDrawable(Drawable drawable) {
		if (DEBUG)
			Log.v(TAG, "setImageDrawable");
		if (drawable != null) {
			imageWidth = drawable.getIntrinsicWidth();
			imageHeight = drawable.getIntrinsicHeight();
			if (DEBUG)
				Log.v(TAG, "setImageDrawable: origin image size " + imageWidth
						+ " " + imageHeight);
			if (round) {
				imageWidth = imageWidth < imageHeight ? imageWidth
						: imageHeight;
				imageHeight = imageWidth;
				fitType = FIT_WIDTH;
				if (DEBUG)
					Log.v(TAG,
							"setImageDrawable: processing rounded image, radius "
									+ imageWidth + "/2");
				if (drawable instanceof BitmapDrawable) {
					Bitmap b = ((BitmapDrawable) drawable).getBitmap();
					b = ImageUtil.getRoundedBitmap(b);
					BitmapDrawable bitmapDrawable = new BitmapDrawable(b);
					super.setImageDrawable(bitmapDrawable);
					return;
				} else {
					if (DEBUG)
						Log.e(TAG,
								"setImageDrawable: round requested, but the drawable assigned is NOT BitmapDrawable");
				}
			} else if (radiusX > 0 || radiusY > 0) {
				if (DEBUG)
					Log.v(TAG,
							"setImageDrawable: processing corner rouned image, radius "
									+ radiusX + " " + radiusY);
				if (drawable instanceof BitmapDrawable) {
					Bitmap b = ((BitmapDrawable) drawable).getBitmap();
					b = ImageUtil.getCornerRoundedBitmap(b, radiusX, radiusY);
					BitmapDrawable bitmapDrawable = new BitmapDrawable(b);
					super.setImageDrawable(bitmapDrawable);
					return;
				}
			}
		}
		super.setImageDrawable(drawable);
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		int w = MeasureSpec.getSize(widthMeasureSpec);
		int h = MeasureSpec.getSize(heightMeasureSpec);
		int wMode = MeasureSpec.getMode(widthMeasureSpec);
		int hMode = MeasureSpec.getMode(heightMeasureSpec);
		if (wMode == MeasureSpec.AT_MOST) {
			if (DEBUG)
				Log.v(TAG, "onMeasure: parent suggest width at most " + w);
		} else if (wMode == MeasureSpec.EXACTLY) {
			if (DEBUG)
				Log.v(TAG, "onMeasure: parent suggest width exactly " + w);
		} else if (wMode == MeasureSpec.UNSPECIFIED) {
			if (DEBUG)
				Log.v(TAG, "onMeasure: parent suggest width unspecified " + w);
		}
		if (hMode == MeasureSpec.AT_MOST) {
			if (DEBUG)
				Log.v(TAG, "onMeasure: parent suggest height at most " + h);
		} else if (hMode == MeasureSpec.EXACTLY) {
			if (DEBUG)
				Log.v(TAG, "onMeasure: parent suggest height exactly " + h);
		} else if (hMode == MeasureSpec.UNSPECIFIED) {
			if (DEBUG)
				Log.v(TAG, "onMeasure: parent suggest height unspecified " + h);
		}
		if (fitType == -1) {
			if (DEBUG)
				Log.v(TAG, "onMeasure: using default scale strategy");

			super.onMeasure(widthMeasureSpec, heightMeasureSpec);
			return;
		}

		if (DEBUG)
			Log.v(TAG, "onMeasure: image size " + imageWidth + " "
					+ imageHeight);
		if (imageWidth == -1 || imageHeight == -1) {
			super.onMeasure(widthMeasureSpec, heightMeasureSpec);
			return;
		}

		if (fitType == FIT_WIDTH) {

			if (wMode == MeasureSpec.UNSPECIFIED) {
				w = imageWidth;
			} else if (wMode == MeasureSpec.AT_MOST) {
				w = Math.min(imageWidth, w);
			}
			h = (int) (w * imageHeight * 1f / imageWidth);
			if (DEBUG)
				Log.v(TAG, "onMeasure: fit width from " + imageWidth + " "
						+ imageHeight + " to " + w + " " + h);
		} else {

			if (hMode == MeasureSpec.UNSPECIFIED) {
				h = imageHeight;
			} else if (hMode == MeasureSpec.AT_MOST) {
				h = Math.min(imageHeight, h);
			}
			w = (int) (h * imageWidth * 1f / imageHeight);
			if (DEBUG)
				Log.v(TAG, "onMeasure: fit height from " + imageWidth + " "
						+ imageHeight + " to " + w + " " + h);
		}
		setMeasuredDimension(w, h);
	}
}
